#pragma once 
#include <list>
#include <map>
#include <vector>
#include <mutex>
#include <thread>
#include <memory>
#include <functional>
#include <GL/gl3w.h>
#include <GLFW/glfw3.h>
#include <config/config.h>
#include <agent/AgentComponent.h>
#include <messageQueue/messageQueue.h>

using namespace std;
class Agent;

class IAgentComponent{
public:
    virtual void Init(){};
    virtual void BeforeUpdate(){};
    virtual void Update(){};
    virtual void AfterUpdate(){};
    virtual void BeforeEnd(){};
    virtual void PollMessage(Message message){};
    IAgentComponent(AgentComponentType m_type,bool loadDepend);
    IAgentComponent() = delete;
public:
    AgentComponentType m_type;
    bool loadDone = false;
    bool loadDepend = false;
    Agent * agent;
};
class Agent : private Config,public MessageQueue{
public:
    void AddComponent(string componentKey,shared_ptr<IAgentComponent> component);
    void Update();
    bool Init();
    void Event();
    void Clear();
    bool ShouldClose();
    GLFWwindow * GetWindow();
    Agent();
    ~Agent();
private:
    void Thread_load(shared_ptr<IAgentComponent> componet);
    bool InitGLFW();
    void ReadConfig();
    void UpdateMessage();
    bool CheckComponentLoad(shared_ptr<IAgentComponent> component);
private:
    GLFWwindow * m_window = nullptr;
    float backcolor[4];
    mutex mutex_load_count;
    bool allLoadDone = false;
    int haveLoadDone = 0;

    map<string, shared_ptr<IAgentComponent> > components;
};
